<template>
  <div>
    <div class="avatar-uploader" :class="{ 'disabled': disabled }" :style="imgStyle">
      <img v-if="cropImg" :src="cropImg" class="avatar" alt="" />
      <el-icon v-else class="avatar-uploader-icon" :style="imgStyle">
        <Plus />
      </el-icon>
      <input
        ref="imgFileRef"
        :disabled="disabled"
        type="file"
        name="image"
        class="upload-input"
        accept="image/*"
        @change="setImage"
      />
    </div>

    <el-dialog
      v-model="dialogVisible"
      title="裁剪图片"
      width="30%"
    >
      <vue-cropper
        ref="cropperRef"
        :img="imgSrc"
        :info="true"
        :auto-crop="autoCrop"
        :auto-crop-width="autoCropWidth||imgWidth"
        :auto-crop-height="autoCropHeight||imgHeight"
        :fixed-box="fixedBox"
        @real-time="realTime"
        style="width:100%;height:300px;"
      />
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="cancelCrop">取 消</el-button>
          <el-button type="primary" @click="dialogVisible = false">确 定</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ElMessageBox } from 'element-plus'
import { Plus } from '@element-plus/icons-vue'
import { VueCropper } from "vue-cropper"
import 'vue-cropper/dist/index.css'
import oss from "@/plugins/ossUtil.js"

const props = defineProps({
  currentImg: {
    type: String,
    default: ''
  },
  autoCrop: {
    type: Boolean,
    default: true
  },
  imgWidth: {
    type: Number,
    default: 160
  },
  imgHeight: {
    type: Number,
    default: 160
  },
  autoHeight: {
    type: Boolean,
    default: false
  },
  uploadPath: {
    type: String,
    default: ''
  },
  disabled: {
    type: Boolean,
    default: false
  },
  autoCropWidth: {
    type: Number,
    default: undefined
  },
  autoCropHeight: {
    type: Number,
    default: undefined
  },
  fixedBox: {
    type: Boolean,
    default: false
  }
})

const emit = defineEmits(['imgUpload', 'selectImg'])

// refs
const imgFileRef = ref(null)
const cropperRef = ref(null)

// 响应式数据
const cropImg = ref(props.currentImg)
const imgSrc = ref('')
const dialogVisible = ref(false)
const fileInfo = ref({
  name: '',
  type: ''
})

// 计算属性
const imgStyle = computed(() => {
  return {
    'width': props.imgWidth + 'px',
    [props.autoHeight ? 'min-height' : 'height']: props.imgHeight + 'px',
    'line-height': props.imgHeight + 'px'
  }
})

// 监听属性
watch(() => props.currentImg, (val) => {
  cropImg.value = val
}, {immediate: true})

watch(() => cropImg.value, (val) => {
  if (val) {
    emit('imgUpload', val)
  }
})
// 方法
const setImage = async (e) => {
  const file = e.target.files[0]
  if (!file.type.includes('image/')) {
    return
  }
  fileInfo.value.name = file.name
  fileInfo.value.type = file.type

  if (!window.FileReader) return
  const reader = new FileReader()
  reader.onload = async (event) => {
    try {
      await ElMessageBox.confirm('是否需要裁剪?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      })
      dialogVisible.value = true
      imgSrc.value = event.target.result
      cropperRef.value?.replace(event.target.result)
    } catch {
      cropImg.value = event.target.result
      emit('selectImg', cropImg.value)
    }
    imgFileRef.value.value = ''
  }
  reader.readAsDataURL(file)
}

const cancelCrop = () => {
  dialogVisible.value = false
  cropImg.value = imgSrc.value
  emit('selectImg', cropImg.value)
}

const isEmpty = () => {
  return !cropImg.value
}

const uploadImage = async () => {
  if (!cropImg.value) {
    return null
  }
  if (cropImg.value.indexOf('base64') > 0) {
    const retUrl = await oss.upload(cropImg.value, props.uploadPath)
    if (retUrl) {
      return retUrl
    }
  }
  return cropImg.value
}

function realTime() {
  cropperRef.value.getCropData(data => {
    cropImg.value = data
    emit('selectImg', cropImg.value)
  })
}

// 暴露方法供父组件使用
defineExpose({
  isEmpty,
  uploadImage
})
</script>

<style lang="scss" scoped>
.avatar-uploader {
  display: inline-block;
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  position: relative;
  overflow: hidden;
  color: #97a8be;
  font-size: 14px;
  text-align: center;
  outline: none;
  background-color: #fff;

  .avatar-uploader-icon {
    font-size: 28px;
    color: #8c939d;
    text-align: center;
  }

  .avatar {
    width: 100%;
    height: 100%;
    display: inline-block;
  }

  .upload-input {
    width: 100%;
    height: 100%;
    z-index: 1;
    opacity: 0;
    position: absolute;
    left: 0;
    top: 0;
    cursor: pointer;
  }

  &.disabled {

    .avatar {
      opacity: 0.5;
    }

    .upload-input {
      cursor: not-allowed;
    }

    &:hover {
      border-color: #d9d9d9;
    }

    &::after {
      content: '';
      position: absolute;
      left: 0;
      top: 0;
      right: 0;
      bottom: 0;
      background-color: rgba(228, 231, 237, 0.3); /* 透明灰色的遮罩层 */
      border-radius: 6px;
      cursor: not-allowed;
      opacity: 0.5; /* 可选，让元素看起来更像是被禁用的 */
    }

  }
}

.avatar-uploader:hover {
  border-color: #409EFF;
}

:deep(.el-overlay-dialog){
  display: flex !important;
  justify-content: center !important;
}
</style>
